// Copyright 2015 The Cockroach Authors.
// Copyright (c) 2022-present, Shanghai Yunxi Technology Co, Ltd. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// This software (KWDB) is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
//          http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.

package sqlbase

import (
	"fmt"
	"time"

	"gitee.com/kwbasedb/kwbase/pkg/config/zonepb"
	"gitee.com/kwbasedb/kwbase/pkg/keys"
	"gitee.com/kwbasedb/kwbase/pkg/roachpb"
	"gitee.com/kwbasedb/kwbase/pkg/security"
	"gitee.com/kwbasedb/kwbase/pkg/sql/privilege"
	"gitee.com/kwbasedb/kwbase/pkg/sql/types"
	"gitee.com/kwbasedb/kwbase/pkg/util/protoutil"
)

// ShouldSplitAtID determines whether a specific descriptor ID
// should be considered for a split at all. If it is a database
// or a view table descriptor, it should not be considered.
func ShouldSplitAtID(id uint32, rawDesc *roachpb.Value) bool {
	var desc Descriptor
	if err := rawDesc.GetProto(&desc); err != nil {
		return false
	}
	if dbDesc := desc.GetDatabase(); dbDesc != nil {
		return false
	}
	if scDesc := desc.GetSchema(); scDesc != nil {
		return false
	}
	if tableDesc := desc.Table(rawDesc.Timestamp); tableDesc != nil {
		if viewStr := tableDesc.GetViewQuery(); viewStr != "" {
			return false
		}
	}
	return true
}

// sql CREATE commands and full schema for each system table.
// These strings are *not* used at runtime, but are checked by the
// `TestSystemTableLiterals` test that compares the table generated by
// evaluating the `CREATE TABLE` statement to the descriptor literal that is
// actually used at runtime.

// These system tables are part of the system config.
const (
	NamespaceTableSchema = `
CREATE TABLE system.namespace2 (
  "parentID" INT8,
  "parentSchemaID" INT8,
  name       STRING,
  id         INT8,
  PRIMARY KEY ("parentID", "parentSchemaID", name)
);`

	DescriptorTableSchema = `
CREATE TABLE system.descriptor (
  id         INT8 PRIMARY KEY,
  descriptor BYTES
);`

	UsersTableSchema = `
CREATE TABLE system.users (
  username         STRING PRIMARY KEY,
  "hashedPassword" BYTES,
  "isRole"         BOOL NOT NULL DEFAULT false
);`

	RoleOptionsTableSchema = `
CREATE TABLE system.role_options (
	username STRING NOT NULL,
	option STRING NOT NULL,
	value STRING,
	PRIMARY KEY (username, option),
	FAMILY "primary" (username, option, value)
)`

	// one record per SCHEDULE
	ScheduledJobsTableSchema = `
CREATE TABLE system.scheduled_jobs (
    schedule_id      INT8 DEFAULT unique_rowid() PRIMARY KEY NOT NULL,
    schedule_name    STRING NOT NULL,
    created          TIMESTAMPTZ NOT NULL DEFAULT now(),
    owner            STRING NOT NULL,
    next_run         TIMESTAMPTZ,
    schedule_state   BYTES,
    schedule_expr    STRING,
    schedule_details BYTES,
    executor_type    STRING NOT NULL,
    execution_args   BYTES NOT NULL,

    INDEX "next_run_idx" (next_run),

    FAMILY sched (schedule_id, next_run, schedule_state),
    FAMILY other (
       schedule_name, created, owner, schedule_expr, 
       schedule_details, executor_type, execution_args 
    )
)`

	// Zone settings per DB/Table.
	ZonesTableSchema = `
CREATE TABLE system.zones (
  id     INT8 PRIMARY KEY,
  config BYTES
);`

	SettingsTableSchema = `
CREATE TABLE system.settings (
	name              STRING    NOT NULL PRIMARY KEY,
	value             STRING    NOT NULL,
	"lastUpdated"     TIMESTAMP NOT NULL DEFAULT now(),
	"valueType"       STRING,
	FAMILY (name, value, "lastUpdated", "valueType")
);`
)

// These system tables are not part of the system config.
const (
	LeaseTableSchema = `
CREATE TABLE system.lease (
  "descID"   INT8,
  version    INT8,
  "nodeID"   INT8,
  expiration TIMESTAMP,
  PRIMARY KEY ("descID", version, expiration, "nodeID")
);`

	EventLogTableSchema = `
CREATE TABLE system.eventlog (
  timestamp     TIMESTAMP  NOT NULL,
  "eventType"   STRING     NOT NULL,
  "targetID"    INT8       NOT NULL,
  "reportingID" INT8       NOT NULL,
  info          STRING,
  "uniqueID"    BYTES      DEFAULT uuid_v4(),
  PRIMARY KEY (timestamp, "uniqueID")
);`

	// rangelog is currently envisioned as a wide table; many different event
	// types can be recorded to the table.
	RangeEventTableSchema = `
CREATE TABLE system.rangelog (
  timestamp      TIMESTAMP  NOT NULL,
  "rangeID"      INT8       NOT NULL,
  "storeID"      INT8       NOT NULL,
  "eventType"    STRING     NOT NULL,
  "otherRangeID" INT8,
  info           STRING,
  "uniqueID"     INT8       DEFAULT unique_rowid(),
  PRIMARY KEY (timestamp, "uniqueID")
);`

	UITableSchema = `
CREATE TABLE system.ui (
	key           STRING PRIMARY KEY,
	value         BYTES,
	"lastUpdated" TIMESTAMP NOT NULL
);`

	// Note: this schema is changed in a migration (a progress column is added in
	// a separate family).
	JobsTableSchema = `
CREATE TABLE system.jobs (
	id                INT8      DEFAULT unique_rowid() PRIMARY KEY,
	status            STRING    NOT NULL,
	created           TIMESTAMP NOT NULL DEFAULT now(),
	payload           BYTES     NOT NULL,
	progress          BYTES,
  created_by_type   STRING,
  created_by_id     INT8,
	INDEX (status, created),
	FAMILY fam_0_id_status_created_payload (id, status, created, payload, created_by_type, created_by_id),
	FAMILY progress (progress)
);`

	// web_sessions are used to track authenticated user actions over stateless
	// connections, such as the cookie-based authentication used by the Admin
	// UI.
	// Design outlined in /docs/RFCS/web_session_login.rfc
	WebSessionsTableSchema = `
CREATE TABLE system.web_sessions (
	id             INT8       NOT NULL DEFAULT unique_rowid() PRIMARY KEY,
	"hashedSecret" BYTES      NOT NULL,
	username       STRING     NOT NULL,
	"createdAt"    TIMESTAMP  NOT NULL DEFAULT now(),
	"expiresAt"    TIMESTAMP  NOT NULL,
	"revokedAt"    TIMESTAMP,
	"lastUsedAt"   TIMESTAMP  NOT NULL DEFAULT now(),
	"auditInfo"    STRING,
	INDEX ("expiresAt"),
	INDEX ("createdAt"),
	FAMILY (id, "hashedSecret", username, "createdAt", "expiresAt", "revokedAt", "lastUsedAt", "auditInfo")
);`

	// table_statistics is used to track statistics collected about individual columns
	// or groups of columns from every table in the database. Each row contains the
	// number of distinct values of the column group and (optionally) a histogram if there
	// is only one column in columnIDs.
	//
	// Design outlined in /docs/RFCS/20170908_sql_optimizer_statistics.md
	TableStatisticsTableSchema = `
CREATE TABLE system.table_statistics (
	"tableID"       INT8       NOT NULL,
	"statisticID"   INT8       NOT NULL DEFAULT unique_rowid(),
	name            STRING,
	"columnIDs"     INT8[]     NOT NULL,
	"createdAt"     TIMESTAMP  NOT NULL DEFAULT now(),
	"rowCount"      INT8       NOT NULL,
	"distinctCount" INT8       NOT NULL,
	"nullCount"     INT8       NOT NULL,
	histogram       BYTES,
	PRIMARY KEY ("tableID", "statisticID"),
	FAMILY ("tableID", "statisticID", name, "columnIDs", "createdAt", "rowCount", "distinctCount", "nullCount", histogram)
);`

	// locations are used to map a locality specified by a node to geographic
	// latitude, longitude coordinates, specified as degrees.
	LocationsTableSchema = `
CREATE TABLE system.locations (
  "localityKey"   STRING,
  "localityValue" STRING,
  latitude        DECIMAL(18,15) NOT NULL,
  longitude       DECIMAL(18,15) NOT NULL,
  PRIMARY KEY ("localityKey", "localityValue"),
  FAMILY ("localityKey", "localityValue", latitude, longitude)
);`

	// role_members stores relationships between roles (role->role and role->user).
	RoleMembersTableSchema = `
CREATE TABLE system.role_members (
  "role"   STRING NOT NULL,
  "member" STRING NOT NULL,
  "isAdmin"  BOOL NOT NULL,
  PRIMARY KEY  ("role", "member"),
  INDEX ("role"),
  INDEX ("member")
);`

	// comments stores comments(database, table, column...).
	CommentsTableSchema = `
CREATE TABLE system.comments (
   type      INT8 NOT NULL,    -- type of object, to distinguish between db, table, column and others
   object_id INT8 NOT NULL,    -- object ID, this will be usually db/table desc ID
   sub_id    INT8 NOT NULL,    -- sub ID for column or indexes inside table, 0 for pure table
   comment   STRING NOT NULL, -- the comment
   PRIMARY KEY (type, object_id, sub_id)
);`

	// protected_ts_meta stores a single row of metadata for the protectedts
	// subsystem.
	ProtectedTimestampsMetaTableSchema = `
CREATE TABLE system.protected_ts_meta (
   singleton   BOOL NOT NULL PRIMARY KEY DEFAULT (true),
   version     INT8 NOT NULL,
   num_records INT8 NOT NULL,
   num_spans   INT8 NOT NULL,
   total_bytes INT8 NOT NULL,
   CONSTRAINT check_singleton  CHECK (singleton),
   FAMILY "primary" (singleton, version, num_records, num_spans, total_bytes)
);`

	ProtectedTimestampsRecordsTableSchema = `
CREATE TABLE system.protected_ts_records (
   id        UUID NOT NULL PRIMARY KEY,
   ts        DECIMAL NOT NULL,
   meta_type STRING NOT NULL,
   meta      BYTES,
   num_spans INT8 NOT NULL, -- num spans is important to know how to decode spans
   spans     BYTES NOT NULL,
   verified  BOOL NOT NULL DEFAULT (false),
   FAMILY "primary" (id, ts, meta_type, meta, num_spans, spans, verified)
);`

	StatementBundleChunksTableSchema = `
CREATE TABLE system.statement_bundle_chunks (
   id          INT8 PRIMARY KEY DEFAULT unique_rowid(),
	 description STRING,
	 data        BYTES NOT NULL,

   FAMILY "primary" (id, description, data)
);`

	StatementDiagnosticsRequestsTableSchema = `
CREATE TABLE system.statement_diagnostics_requests(
	id INT8 DEFAULT unique_rowid() PRIMARY KEY NOT NULL,
	completed BOOL NOT NULL DEFAULT FALSE,
	statement_fingerprint STRING NOT NULL,
	statement_diagnostics_id INT8,
	requested_at TIMESTAMPTZ NOT NULL,
	INDEX completed_idx (completed, id) STORING (statement_fingerprint),

	FAMILY "primary" (id, completed, statement_fingerprint, statement_diagnostics_id, requested_at)
);`

	StatementDiagnosticsTableSchema = `
create table system.statement_diagnostics(
  id INT8 DEFAULT unique_rowid() PRIMARY KEY NOT NULL,
  statement_fingerprint STRING NOT NULL,
  statement STRING NOT NULL,
  collected_at TIMESTAMPTZ NOT NULL,
  trace JSONB,
  bundle_chunks INT8 ARRAY,
	error STRING,

	FAMILY "primary" (id, statement_fingerprint, statement, collected_at, trace, bundle_chunks, error)
);`

	AuditsTableSchema = `
	CREATE TABLE system.audits (
		audit_name	STRING NOT NULL,
		target_type	STRING NOT NULL,
		target_id		INT8,
		operations	STRING[] NOT NULL,
		operators		STRING[] NOT NULL,
		condition		INT8,
		whenever		STRING NOT NULL,
		action		INT8,
		level			INT8,
		enable		BOOL NOT NULL,
		PRIMARY KEY (audit_name),
		FAMILY (audit_name)
	);`
)

func pk(name string) IndexDescriptor {
	return IndexDescriptor{
		Name:             "primary",
		ID:               1,
		Unique:           true,
		ColumnNames:      []string{name},
		ColumnDirections: singleASC,
		ColumnIDs:        singleID1,
		Version:          SecondaryIndexFamilyFormatVersion,
	}
}

// SystemAllowedPrivileges describes the allowable privilege list for each
// system object. Super users (root and admin) must have exactly the specified privileges,
// other users must not exceed the specified privileges.
var SystemAllowedPrivileges = map[ID]privilege.List{
	keys.SystemDatabaseID:           privilege.ReadData,
	keys.NamespaceTableID:           privilege.ReadData,
	keys.DeprecatedNamespaceTableID: privilege.ReadData,
	keys.DescriptorTableID:          privilege.ReadData,
	keys.UsersTableID:               privilege.ReadWriteData,
	keys.RoleOptionsTableID:         privilege.ReadWriteData,
	keys.ZonesTableID:               privilege.ReadWriteData,
	// We eventually want to migrate the table to appear read-only to force the
	// the use of a validating, logging accessor, so we'll go ahead and tolerate
	// read-only privs to make that migration possible later.
	keys.SettingsTableID:      privilege.ReadWriteData,
	keys.LeaseTableID:         privilege.ReadWriteData,
	keys.EventLogTableID:      privilege.ReadWriteData,
	keys.ScheduledJobsTableID: privilege.ReadWriteData,
	keys.RangeEventTableID:    privilege.ReadWriteData,
	keys.UITableID:            privilege.ReadWriteData,
	// IMPORTANT: CREATE|DROP|ALL privileges should always be denied or database
	// users will be able to modify system tables' schemas at will. CREATE and
	// DROP privileges are allowed on the above system tables for backwards
	// compatibility reasons only!
	keys.JobsTableID:                          privilege.ReadWriteData,
	keys.WebSessionsTableID:                   privilege.ReadWriteData,
	keys.TableStatisticsTableID:               privilege.ReadWriteData,
	keys.LocationsTableID:                     privilege.ReadWriteData,
	keys.RoleMembersTableID:                   privilege.ReadWriteData,
	keys.CommentsTableID:                      privilege.ReadWriteData,
	keys.ReplicationConstraintStatsTableID:    privilege.ReadWriteData,
	keys.ReplicationCriticalLocalitiesTableID: privilege.ReadWriteData,
	keys.ReplicationStatsTableID:              privilege.ReadWriteData,
	keys.ReportsMetaTableID:                   privilege.ReadWriteData,
	keys.ProtectedTimestampsMetaTableID:       privilege.ReadData,
	keys.ProtectedTimestampsRecordsTableID:    privilege.ReadData,
	keys.StatementBundleChunksTableID:         privilege.ReadWriteData,
	keys.StatementDiagnosticsRequestsTableID:  privilege.ReadWriteData,
	keys.StatementDiagnosticsTableID:          privilege.ReadWriteData,

	keys.KWDBHAInfoID:              {privilege.DROP},
	keys.KWDBTopicID:               {privilege.DROP},
	keys.KWDBPreComputingID:        {privilege.DROP},
	keys.KWDBObjectRelationID:      {privilege.DROP},
	keys.KWDBNodeInfoID:            {privilege.DROP},
	keys.KWDBReplicationInfoID:     privilege.ReadWriteData,
	keys.KWDBSystemConfigID:        {privilege.DROP},
	keys.KWDBNodeMigrateLogTableID: {privilege.DROP},
	keys.MMNamespaceTableID:        {privilege.DROP},
	keys.AuditsTableID:             privilege.ReadWriteData,
	keys.KWDBBoBlackListTableID:    privilege.ReadWriteData,
	keys.KWDBTsTableID:             privilege.ReadWriteData,

	keys.MLModelsTableID:            {privilege.DROP},
	keys.MLTrainingPipelinesTableID: {privilege.DROP},
	keys.MLModelVersionsTableID:     {privilege.DROP},
	keys.MLJobsTableID:              {privilege.DROP},
	keys.MLPrivilegesTableID:        {privilege.DROP},
	keys.KWDBShowJobsTableID:        {privilege.DROP},
	keys.KWDBHashRoutingTableID:     privilege.ReadData,
	keys.DefinedFunctionTableID:     privilege.ReadWriteData,
}

// Helpers used to make some of the TableDescriptor literals below more concise.
var (
	singleASC = []IndexDescriptor_Direction{IndexDescriptor_ASC}
	singleID1 = []ColumnID{1}
)

// MakeSystemDatabaseDesc constructs a copy of the system database
// descriptor.
func MakeSystemDatabaseDesc() DatabaseDescriptor {
	return DatabaseDescriptor{
		Name: "system",
		ID:   keys.SystemDatabaseID,
		// Assign max privileges to root user.
		Privileges: NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.SystemDatabaseID]),
	}
}

// These system config TableDescriptor literals should match the descriptor
// that would be produced by evaluating one of the above `CREATE TABLE`
// statements. See the `TestSystemTableLiterals` which checks that they do
// indeed match, and has suggestions on writing and maintaining them.
var (
	// SystemDB is the descriptor for the system database.
	SystemDB = MakeSystemDatabaseDesc()

	// NamespaceTableName is "namespace", which is always and forever the
	// user-visible name of the system.namespace table. Tautological, but
	// important.
	NamespaceTableName = "namespace"

	// DeprecatedNamespaceTable is the descriptor for the deprecated namespace table.
	DeprecatedNamespaceTable = TableDescriptor{
		Name:                    NamespaceTableName,
		ID:                      keys.DeprecatedNamespaceTableID,
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "parentID", ID: 1, Type: *types.Int},
			{Name: "name", ID: 2, Type: *types.String},
			{Name: "id", ID: 3, Type: *types.Int, Nullable: true},
		},
		NextColumnID: 4,
		Families: []ColumnFamilyDescriptor{
			{Name: "primary", ID: 0, ColumnNames: []string{"parentID", "name"}, ColumnIDs: []ColumnID{1, 2}},
			{Name: "fam_3_id", ID: 3, ColumnNames: []string{"id"}, ColumnIDs: []ColumnID{3}, DefaultColumnID: 3},
		},
		NextFamilyID: 4,
		PrimaryIndex: IndexDescriptor{
			Name:             "primary",
			ID:               1,
			Unique:           true,
			ColumnNames:      []string{"parentID", "name"},
			ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC, IndexDescriptor_ASC},
			ColumnIDs:        []ColumnID{1, 2},
			Version:          SecondaryIndexFamilyFormatVersion,
		},
		NextIndexID:    2,
		Privileges:     NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.DeprecatedNamespaceTableID]),
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}

	// NamespaceTable is the descriptor for the namespace table. Note that this
	// table should only be written to via KV puts, not via the SQL layer. Some
	// code assumes that it only has KV entries for column family 4, not the
	// "sentinel" column family 0 which would be written by SQL.
	//
	// Note that the Descriptor.Name of this table is not "namespace", but
	// something else. This is because, in 20.1, we moved the representation of
	// namespaces to a new place, and for various reasons, we can't have two
	// descriptors with the same Name at once.
	//
	// TODO(solon): in 20.2, we should change the Name of this descriptor
	// back to "namespace".
	NamespaceTable = TableDescriptor{
		Name:                    "namespace2",
		ID:                      keys.NamespaceTableID,
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "parentID", ID: 1, Type: *types.Int},
			{Name: "parentSchemaID", ID: 2, Type: *types.Int},
			{Name: "name", ID: 3, Type: *types.String},
			{Name: "id", ID: 4, Type: *types.Int, Nullable: true},
		},
		NextColumnID: 5,
		Families: []ColumnFamilyDescriptor{
			{Name: "primary", ID: 0, ColumnNames: []string{"parentID", "parentSchemaID", "name"}, ColumnIDs: []ColumnID{1, 2, 3}},
			{Name: "fam_4_id", ID: 4, ColumnNames: []string{"id"}, ColumnIDs: []ColumnID{4}, DefaultColumnID: 4},
		},
		NextFamilyID: 5,
		PrimaryIndex: IndexDescriptor{
			Name:             "primary",
			ID:               1,
			Unique:           true,
			ColumnNames:      []string{"parentID", "parentSchemaID", "name"},
			ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC, IndexDescriptor_ASC, IndexDescriptor_ASC},
			ColumnIDs:        []ColumnID{1, 2, 3},
			Version:          SecondaryIndexFamilyFormatVersion,
		},
		NextIndexID:    2,
		Privileges:     NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.DeprecatedNamespaceTableID]),
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}

	uuidV4String = "uuid_v4()"

	// EventLogTable is the descriptor for the event log table.
	EventLogTable = TableDescriptor{
		Name:                    "eventlog",
		ID:                      keys.EventLogTableID,
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "timestamp", ID: 1, Type: *types.Timestamp},
			{Name: "eventType", ID: 2, Type: *types.String},
			{Name: "targetID", ID: 3, Type: *types.Int},
			{Name: "reportingID", ID: 4, Type: *types.Int},
			{Name: "info", ID: 5, Type: *types.String, Nullable: true},
			{Name: "uniqueID", ID: 6, Type: *types.Bytes, DefaultExpr: &uuidV4String},
		},
		NextColumnID: 7,
		Families: []ColumnFamilyDescriptor{
			{Name: "primary", ID: 0, ColumnNames: []string{"timestamp", "uniqueID"}, ColumnIDs: []ColumnID{1, 6}},
			{Name: "fam_2_eventType", ID: 2, ColumnNames: []string{"eventType"}, ColumnIDs: []ColumnID{2}, DefaultColumnID: 2},
			{Name: "fam_3_targetID", ID: 3, ColumnNames: []string{"targetID"}, ColumnIDs: []ColumnID{3}, DefaultColumnID: 3},
			{Name: "fam_4_reportingID", ID: 4, ColumnNames: []string{"reportingID"}, ColumnIDs: []ColumnID{4}, DefaultColumnID: 4},
			{Name: "fam_5_info", ID: 5, ColumnNames: []string{"info"}, ColumnIDs: []ColumnID{5}, DefaultColumnID: 5},
		},
		PrimaryIndex: IndexDescriptor{
			Name:             "primary",
			ID:               1,
			Unique:           true,
			ColumnNames:      []string{"timestamp", "uniqueID"},
			ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC, IndexDescriptor_ASC},
			ColumnIDs:        []ColumnID{1, 6},
			Version:          SecondaryIndexFamilyFormatVersion,
		},
		NextFamilyID:   6,
		NextIndexID:    2,
		Privileges:     NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.EventLogTableID]),
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}

	nowTZString = "now():::TIMESTAMPTZ"
	// ScheduledJobsTable is the descriptor for the scheduled jobs table.
	ScheduledJobsTable = TableDescriptor{
		Name:                    "scheduled_jobs",
		ID:                      keys.ScheduledJobsTableID,
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{ID: 1, Name: "schedule_id", Type: *types.Int, DefaultExpr: &uniqueRowIDString, Nullable: false},
			{Name: "schedule_name", ID: 2, Type: *types.String, Nullable: false},
			{ID: 3, Name: "created", Type: *types.TimestampTZ, DefaultExpr: &nowTZString, Nullable: false},
			{Name: "owner", ID: 4, Type: *types.String, Nullable: false},
			{ID: 5, Name: "next_run", Type: *types.TimestampTZ, Nullable: true},
			{ID: 6, Name: "schedule_state", Type: *types.Bytes, Nullable: true},
			{Name: "schedule_expr", ID: 7, Type: *types.String, Nullable: true},
			{ID: 8, Name: "schedule_details", Type: *types.Bytes, Nullable: true},
			{Name: "executor_type", ID: 9, Type: *types.String, Nullable: false},
			{ID: 10, Name: "execution_args", Type: *types.Bytes, Nullable: false},
		},
		NextColumnID: 11,
		Families: []ColumnFamilyDescriptor{
			{
				ID:          0,
				ColumnNames: []string{"schedule_id", "next_run", "schedule_state"},
				ColumnIDs:   []ColumnID{1, 5, 6},
				Name:        "sched",
			},
			{
				Name: "other",
				ID:   1,
				ColumnNames: []string{"schedule_name", "created", "owner", "schedule_expr", "schedule_details",
					"executor_type", "execution_args"},
				ColumnIDs: []ColumnID{2, 3, 4, 7, 8, 9, 10},
			},
		},
		NextFamilyID: 2,
		PrimaryIndex: pk("schedule_id"),
		Indexes: []IndexDescriptor{
			{
				ColumnNames:      []string{"next_run"},
				ID:               2,
				Unique:           false,
				ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC},
				ColumnIDs:        []ColumnID{5},
				ExtraColumnIDs:   []ColumnID{1},
				Version:          SecondaryIndexFamilyFormatVersion,
				Name:             "next_run_idx",
			},
		},
		NextIndexID:    3,
		Privileges:     NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.ScheduledJobsTableID]),
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}

	// DescriptorTable is the descriptor for the descriptor table.
	DescriptorTable = TableDescriptor{
		Name:                    "descriptor",
		ID:                      keys.DescriptorTableID,
		Privileges:              NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.DescriptorTableID]),
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "id", ID: 1, Type: *types.Int},
			{Name: "descriptor", ID: keys.DescriptorTableDescriptorColID, Type: *types.Bytes, Nullable: true},
		},
		NextColumnID: 3,
		Families: []ColumnFamilyDescriptor{
			// The id of the first col fam is hardcoded in keys.MakeDescMetadataKey().
			{Name: "primary", ID: 0, ColumnNames: []string{"id"}, ColumnIDs: singleID1},
			{Name: "fam_2_descriptor", ID: keys.DescriptorTableDescriptorColFamID,
				ColumnNames: []string{"descriptor"},
				ColumnIDs:   []ColumnID{keys.DescriptorTableDescriptorColID}, DefaultColumnID: keys.DescriptorTableDescriptorColID},
		},
		PrimaryIndex:   pk("id"),
		NextFamilyID:   3,
		NextIndexID:    2,
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}

	falseBoolString = "false"
	trueBoolString  = "true"

	// UsersTable is the descriptor for the users table.
	UsersTable = TableDescriptor{
		Name:                    "users",
		ID:                      keys.UsersTableID,
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "username", ID: 1, Type: *types.String},
			{Name: "hashedPassword", ID: 2, Type: *types.Bytes, Nullable: true},
			{Name: "isRole", ID: 3, Type: *types.Bool, DefaultExpr: &falseBoolString},
		},
		NextColumnID: 4,
		Families: []ColumnFamilyDescriptor{
			{Name: "primary", ID: 0, ColumnNames: []string{"username"}, ColumnIDs: singleID1},
			{Name: "fam_2_hashedPassword", ID: 2, ColumnNames: []string{"hashedPassword"}, ColumnIDs: []ColumnID{2}, DefaultColumnID: 2},
			{Name: "fam_3_isRole", ID: 3, ColumnNames: []string{"isRole"}, ColumnIDs: []ColumnID{3}, DefaultColumnID: 3},
		},
		PrimaryIndex:   pk("username"),
		NextFamilyID:   4,
		NextIndexID:    2,
		Privileges:     NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.UsersTableID]),
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}

	// ZonesTable is the descriptor for the zones table.
	ZonesTable = TableDescriptor{
		Name:                    "zones",
		ID:                      keys.ZonesTableID,
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "id", ID: 1, Type: *types.Int},
			{Name: "config", ID: keys.ZonesTableConfigColumnID, Type: *types.Bytes, Nullable: true},
		},
		NextColumnID: 3,
		Families: []ColumnFamilyDescriptor{
			{Name: "primary", ID: 0, ColumnNames: []string{"id"}, ColumnIDs: singleID1},
			{Name: "fam_2_config", ID: keys.ZonesTableConfigColFamID, ColumnNames: []string{"config"},
				ColumnIDs: []ColumnID{keys.ZonesTableConfigColumnID}, DefaultColumnID: keys.ZonesTableConfigColumnID},
		},
		PrimaryIndex: IndexDescriptor{
			Name:             "primary",
			ID:               keys.ZonesTablePrimaryIndexID,
			Unique:           true,
			ColumnNames:      []string{"id"},
			ColumnDirections: singleASC,
			ColumnIDs:        []ColumnID{keys.ZonesTablePrimaryIndexID},
			Version:          SecondaryIndexFamilyFormatVersion,
		},
		NextFamilyID:   3,
		NextIndexID:    2,
		Privileges:     NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.ZonesTableID]),
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}

	// SettingsTable is the descriptor for the settings table.
	// It contains all cluster settings for which a value has been set.
	SettingsTable = TableDescriptor{
		Name:                    "settings",
		ID:                      keys.SettingsTableID,
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "name", ID: 1, Type: *types.String},
			{Name: "value", ID: 2, Type: *types.String},
			{Name: "lastUpdated", ID: 3, Type: *types.Timestamp, DefaultExpr: &nowString},
			{Name: "valueType", ID: 4, Type: *types.String, Nullable: true},
		},
		NextColumnID: 5,
		Families: []ColumnFamilyDescriptor{
			{
				Name:        "fam_0_name_value_lastUpdated_valueType",
				ID:          0,
				ColumnNames: []string{"name", "value", "lastUpdated", "valueType"},
				ColumnIDs:   []ColumnID{1, 2, 3, 4},
			},
		},
		NextFamilyID:   1,
		PrimaryIndex:   pk("name"),
		NextIndexID:    2,
		Privileges:     NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.SettingsTableID]),
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}
)

// These system TableDescriptor literals should match the descriptor that
// would be produced by evaluating one of the above `CREATE TABLE` statements
// for system tables that are not system config tables. See the
// `TestSystemTableLiterals` which checks that they do indeed match, and has
// suggestions on writing and maintaining them.
var (
	// LeaseTable is the descriptor for the leases table.
	LeaseTable = TableDescriptor{
		Name:                    "lease",
		ID:                      keys.LeaseTableID,
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "descID", ID: 1, Type: *types.Int},
			{Name: "version", ID: 2, Type: *types.Int},
			{Name: "nodeID", ID: 3, Type: *types.Int},
			{Name: "expiration", ID: 4, Type: *types.Timestamp},
		},
		NextColumnID: 5,
		Families: []ColumnFamilyDescriptor{
			{Name: "primary", ID: 0, ColumnNames: []string{"descID", "version", "nodeID", "expiration"}, ColumnIDs: []ColumnID{1, 2, 3, 4}},
		},
		PrimaryIndex: IndexDescriptor{
			Name:             "primary",
			ID:               1,
			Unique:           true,
			ColumnNames:      []string{"descID", "version", "expiration", "nodeID"},
			ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC, IndexDescriptor_ASC, IndexDescriptor_ASC, IndexDescriptor_ASC},
			ColumnIDs:        []ColumnID{1, 2, 4, 3},
			Version:          SecondaryIndexFamilyFormatVersion,
		},
		NextFamilyID:   1,
		NextIndexID:    2,
		Privileges:     NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.LeaseTableID]),
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}

	uniqueRowIDString = "unique_rowid()"

	// RangeEventTable is the descriptor for the range log table.
	RangeEventTable = TableDescriptor{
		Name:                    "rangelog",
		ID:                      keys.RangeEventTableID,
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "timestamp", ID: 1, Type: *types.Timestamp},
			{Name: "rangeID", ID: 2, Type: *types.Int},
			{Name: "storeID", ID: 3, Type: *types.Int},
			{Name: "eventType", ID: 4, Type: *types.String},
			{Name: "otherRangeID", ID: 5, Type: *types.Int, Nullable: true},
			{Name: "info", ID: 6, Type: *types.String, Nullable: true},
			{Name: "uniqueID", ID: 7, Type: *types.Int, DefaultExpr: &uniqueRowIDString},
		},
		NextColumnID: 8,
		Families: []ColumnFamilyDescriptor{
			{Name: "primary", ID: 0, ColumnNames: []string{"timestamp", "uniqueID"}, ColumnIDs: []ColumnID{1, 7}},
			{Name: "fam_2_rangeID", ID: 2, ColumnNames: []string{"rangeID"}, ColumnIDs: []ColumnID{2}, DefaultColumnID: 2},
			{Name: "fam_3_storeID", ID: 3, ColumnNames: []string{"storeID"}, ColumnIDs: []ColumnID{3}, DefaultColumnID: 3},
			{Name: "fam_4_eventType", ID: 4, ColumnNames: []string{"eventType"}, ColumnIDs: []ColumnID{4}, DefaultColumnID: 4},
			{Name: "fam_5_otherRangeID", ID: 5, ColumnNames: []string{"otherRangeID"}, ColumnIDs: []ColumnID{5}, DefaultColumnID: 5},
			{Name: "fam_6_info", ID: 6, ColumnNames: []string{"info"}, ColumnIDs: []ColumnID{6}, DefaultColumnID: 6},
		},
		PrimaryIndex: IndexDescriptor{
			Name:             "primary",
			ID:               1,
			Unique:           true,
			ColumnNames:      []string{"timestamp", "uniqueID"},
			ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC, IndexDescriptor_ASC},
			ColumnIDs:        []ColumnID{1, 7},
			Version:          SecondaryIndexFamilyFormatVersion,
		},
		NextFamilyID:   7,
		NextIndexID:    2,
		Privileges:     NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.RangeEventTableID]),
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}

	// UITable is the descriptor for the ui table.
	UITable = TableDescriptor{
		Name:                    "ui",
		ID:                      keys.UITableID,
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "key", ID: 1, Type: *types.String},
			{Name: "value", ID: 2, Type: *types.Bytes, Nullable: true},
			{Name: "lastUpdated", ID: 3, Type: *types.Timestamp},
		},
		NextColumnID: 4,
		Families: []ColumnFamilyDescriptor{
			{Name: "primary", ID: 0, ColumnNames: []string{"key"}, ColumnIDs: singleID1},
			{Name: "fam_2_value", ID: 2, ColumnNames: []string{"value"}, ColumnIDs: []ColumnID{2}, DefaultColumnID: 2},
			{Name: "fam_3_lastUpdated", ID: 3, ColumnNames: []string{"lastUpdated"}, ColumnIDs: []ColumnID{3}, DefaultColumnID: 3},
		},
		NextFamilyID:   4,
		PrimaryIndex:   pk("key"),
		NextIndexID:    2,
		Privileges:     NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.UITableID]),
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}

	nowString = "now():::TIMESTAMP"

	// JobsTable is the descriptor for the jobs table.
	JobsTable = TableDescriptor{
		Name:                    "jobs",
		ID:                      keys.JobsTableID,
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "id", ID: 1, Type: *types.Int, DefaultExpr: &uniqueRowIDString},
			{Name: "status", ID: 2, Type: *types.String},
			{Name: "created", ID: 3, Type: *types.Timestamp, DefaultExpr: &nowString},
			{Name: "payload", ID: 4, Type: *types.Bytes},
			{Name: "progress", ID: 5, Type: *types.Bytes, Nullable: true},
			{Name: "created_by_type", ID: 6, Type: *types.String, Nullable: true},
			{Name: "created_by_id", ID: 7, Type: *types.Int, Nullable: true},
		},
		NextColumnID: 8,
		Families: []ColumnFamilyDescriptor{
			{
				Name:        "fam_0_id_status_created_payload",
				ID:          0,
				ColumnNames: []string{"id", "status", "created", "payload", "created_by_type", "created_by_id"},
				ColumnIDs:   []ColumnID{1, 2, 3, 4, 6, 7},
			},
			{
				Name:            "progress",
				ID:              1,
				ColumnNames:     []string{"progress"},
				ColumnIDs:       []ColumnID{5},
				DefaultColumnID: 5,
			},
		},
		NextFamilyID: 2,
		PrimaryIndex: pk("id"),
		Indexes: []IndexDescriptor{
			{
				Name:             "jobs_status_created_idx",
				ID:               2,
				Unique:           false,
				ColumnNames:      []string{"status", "created"},
				ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC, IndexDescriptor_ASC},
				ColumnIDs:        []ColumnID{2, 3},
				ExtraColumnIDs:   []ColumnID{1},
				Version:          SecondaryIndexFamilyFormatVersion,
			},
		},
		NextIndexID:    3,
		Privileges:     NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.JobsTableID]),
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}

	// WebSessions table to authenticate sessions over stateless connections.
	WebSessionsTable = TableDescriptor{
		Name:                    "web_sessions",
		ID:                      keys.WebSessionsTableID,
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "id", ID: 1, Type: *types.Int, DefaultExpr: &uniqueRowIDString},
			{Name: "hashedSecret", ID: 2, Type: *types.Bytes},
			{Name: "username", ID: 3, Type: *types.String},
			{Name: "createdAt", ID: 4, Type: *types.Timestamp, DefaultExpr: &nowString},
			{Name: "expiresAt", ID: 5, Type: *types.Timestamp},
			{Name: "revokedAt", ID: 6, Type: *types.Timestamp, Nullable: true},
			{Name: "lastUsedAt", ID: 7, Type: *types.Timestamp, DefaultExpr: &nowString},
			{Name: "auditInfo", ID: 8, Type: *types.String, Nullable: true},
		},
		NextColumnID: 9,
		Families: []ColumnFamilyDescriptor{
			{
				Name: "fam_0_id_hashedSecret_username_createdAt_expiresAt_revokedAt_lastUsedAt_auditInfo",
				ID:   0,
				ColumnNames: []string{
					"id",
					"hashedSecret",
					"username",
					"createdAt",
					"expiresAt",
					"revokedAt",
					"lastUsedAt",
					"auditInfo",
				},
				ColumnIDs: []ColumnID{1, 2, 3, 4, 5, 6, 7, 8},
			},
		},
		NextFamilyID: 1,
		PrimaryIndex: pk("id"),
		Indexes: []IndexDescriptor{
			{
				Name:             "web_sessions_expiresAt_idx",
				ID:               2,
				Unique:           false,
				ColumnNames:      []string{"expiresAt"},
				ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC},
				ColumnIDs:        []ColumnID{5},
				ExtraColumnIDs:   []ColumnID{1},
				Version:          SecondaryIndexFamilyFormatVersion,
			},
			{
				Name:             "web_sessions_createdAt_idx",
				ID:               3,
				Unique:           false,
				ColumnNames:      []string{"createdAt"},
				ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC},
				ColumnIDs:        []ColumnID{4},
				ExtraColumnIDs:   []ColumnID{1},
				Version:          SecondaryIndexFamilyFormatVersion,
			},
		},
		NextIndexID:    4,
		Privileges:     NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.WebSessionsTableID]),
		NextMutationID: 1,
		FormatVersion:  3,
	}

	// TableStatistics table to hold statistics about columns and column groups.
	TableStatisticsTable = TableDescriptor{
		Name:                    "table_statistics",
		ID:                      keys.TableStatisticsTableID,
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "tableID", ID: 1, Type: *types.Int},
			{Name: "statisticID", ID: 2, Type: *types.Int, DefaultExpr: &uniqueRowIDString},
			{Name: "name", ID: 3, Type: *types.String, Nullable: true},
			{Name: "columnIDs", ID: 4, Type: *types.IntArray},
			{Name: "createdAt", ID: 5, Type: *types.Timestamp, DefaultExpr: &nowString},
			{Name: "rowCount", ID: 6, Type: *types.Int},
			{Name: "distinctCount", ID: 7, Type: *types.Int},
			{Name: "nullCount", ID: 8, Type: *types.Int},
			{Name: "histogram", ID: 9, Type: *types.Bytes, Nullable: true},
		},
		NextColumnID: 10,
		Families: []ColumnFamilyDescriptor{
			{
				Name: "fam_0_tableID_statisticID_name_columnIDs_createdAt_rowCount_distinctCount_nullCount_histogram",
				ID:   0,
				ColumnNames: []string{
					"tableID",
					"statisticID",
					"name",
					"columnIDs",
					"createdAt",
					"rowCount",
					"distinctCount",
					"nullCount",
					"histogram",
				},
				ColumnIDs: []ColumnID{1, 2, 3, 4, 5, 6, 7, 8, 9},
			},
		},
		NextFamilyID: 1,
		PrimaryIndex: IndexDescriptor{
			Name:             "primary",
			ID:               1,
			Unique:           true,
			ColumnNames:      []string{"tableID", "statisticID"},
			ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC, IndexDescriptor_ASC},
			ColumnIDs:        []ColumnID{1, 2},
			Version:          SecondaryIndexFamilyFormatVersion,
		},
		NextIndexID:    2,
		Privileges:     NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.TableStatisticsTableID]),
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}

	latLonDecimal = types.MakeDecimal(18, 15)

	// LocationsTable is the descriptor for the locations table.
	LocationsTable = TableDescriptor{
		Name:                    "locations",
		ID:                      keys.LocationsTableID,
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "localityKey", ID: 1, Type: *types.String},
			{Name: "localityValue", ID: 2, Type: *types.String},
			{Name: "latitude", ID: 3, Type: *latLonDecimal},
			{Name: "longitude", ID: 4, Type: *latLonDecimal},
		},
		NextColumnID: 5,
		Families: []ColumnFamilyDescriptor{
			{
				Name:        "fam_0_localityKey_localityValue_latitude_longitude",
				ID:          0,
				ColumnNames: []string{"localityKey", "localityValue", "latitude", "longitude"},
				ColumnIDs:   []ColumnID{1, 2, 3, 4},
			},
		},
		NextFamilyID: 1,
		PrimaryIndex: IndexDescriptor{
			Name:             "primary",
			ID:               1,
			Unique:           true,
			ColumnNames:      []string{"localityKey", "localityValue"},
			ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC, IndexDescriptor_ASC},
			ColumnIDs:        []ColumnID{1, 2},
			Version:          SecondaryIndexFamilyFormatVersion,
		},
		NextIndexID:    2,
		Privileges:     NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.LocationsTableID]),
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}

	// RoleMembersTable is the descriptor for the role_members table.
	RoleMembersTable = TableDescriptor{
		Name:                    "role_members",
		ID:                      keys.RoleMembersTableID,
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "role", ID: 1, Type: *types.String},
			{Name: "member", ID: 2, Type: *types.String},
			{Name: "isAdmin", ID: 3, Type: *types.Bool},
		},
		NextColumnID: 4,
		Families: []ColumnFamilyDescriptor{
			{
				Name:        "primary",
				ID:          0,
				ColumnNames: []string{"role", "member"},
				ColumnIDs:   []ColumnID{1, 2},
			},
			{
				Name:            "fam_3_isAdmin",
				ID:              3,
				ColumnNames:     []string{"isAdmin"},
				ColumnIDs:       []ColumnID{3},
				DefaultColumnID: 3,
			},
		},
		NextFamilyID: 4,
		PrimaryIndex: IndexDescriptor{
			Name:             "primary",
			ID:               1,
			Unique:           true,
			ColumnNames:      []string{"role", "member"},
			ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC, IndexDescriptor_ASC},
			ColumnIDs:        []ColumnID{1, 2},
			Version:          SecondaryIndexFamilyFormatVersion,
		},
		Indexes: []IndexDescriptor{
			{
				Name:             "role_members_role_idx",
				ID:               2,
				Unique:           false,
				ColumnNames:      []string{"role"},
				ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC},
				ColumnIDs:        []ColumnID{1},
				ExtraColumnIDs:   []ColumnID{2},
				Version:          SecondaryIndexFamilyFormatVersion,
			},
			{
				Name:             "role_members_member_idx",
				ID:               3,
				Unique:           false,
				ColumnNames:      []string{"member"},
				ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC},
				ColumnIDs:        []ColumnID{2},
				ExtraColumnIDs:   []ColumnID{1},
				Version:          SecondaryIndexFamilyFormatVersion,
			},
		},
		NextIndexID:    4,
		Privileges:     NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.RoleMembersTableID]),
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}

	// CommentsTable is the descriptor for the comments table.
	CommentsTable = TableDescriptor{
		Name:                    "comments",
		ID:                      keys.CommentsTableID,
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "type", ID: 1, Type: *types.Int},
			{Name: "object_id", ID: 2, Type: *types.Int},
			{Name: "sub_id", ID: 3, Type: *types.Int},
			{Name: "comment", ID: 4, Type: *types.String},
		},
		NextColumnID: 5,
		Families: []ColumnFamilyDescriptor{
			{Name: "primary", ID: 0, ColumnNames: []string{"type", "object_id", "sub_id"}, ColumnIDs: []ColumnID{1, 2, 3}},
			{Name: "fam_4_comment", ID: 4, ColumnNames: []string{"comment"}, ColumnIDs: []ColumnID{4}, DefaultColumnID: 4},
		},
		NextFamilyID: 5,
		PrimaryIndex: IndexDescriptor{
			Name:             "primary",
			ID:               1,
			Unique:           true,
			ColumnNames:      []string{"type", "object_id", "sub_id"},
			ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC, IndexDescriptor_ASC, IndexDescriptor_ASC},
			ColumnIDs:        []ColumnID{1, 2, 3},
			Version:          SecondaryIndexFamilyFormatVersion,
		},
		NextIndexID:    2,
		Privileges:     newCommentPrivilegeDescriptor(SystemAllowedPrivileges[keys.CommentsTableID]),
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}

	ReportsMetaTable = TableDescriptor{
		Name:                    "reports_meta",
		ID:                      keys.ReportsMetaTableID,
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "id", ID: 1, Type: *types.Int},
			{Name: "generated", ID: 2, Type: *types.TimestampTZ},
		},
		NextColumnID: 3,
		Families: []ColumnFamilyDescriptor{
			{
				Name:        "primary",
				ID:          0,
				ColumnNames: []string{"id", "generated"},
				ColumnIDs:   []ColumnID{1, 2},
			},
		},
		NextFamilyID: 1,
		PrimaryIndex: IndexDescriptor{
			Name:        "primary",
			ID:          1,
			Unique:      true,
			ColumnNames: []string{"id"},
			ColumnDirections: []IndexDescriptor_Direction{
				IndexDescriptor_ASC,
			},
			ColumnIDs: []ColumnID{1},
			Version:   SecondaryIndexFamilyFormatVersion,
		},
		NextIndexID:    2,
		Privileges:     NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.ReportsMetaTableID]),
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}

	ReplicationConstraintStatsTableTTL = time.Minute * 10
	// TODO(andrei): In 20.1 we should add a foreign key reference to the
	// reports_meta table. Until then, it would cost us having to create an index
	// on report_id.
	ReplicationConstraintStatsTable = TableDescriptor{
		Name:                    "replication_constraint_stats",
		ID:                      keys.ReplicationConstraintStatsTableID,
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "zone_id", ID: 1, Type: *types.Int},
			{Name: "subzone_id", ID: 2, Type: *types.Int},
			{Name: "type", ID: 3, Type: *types.String},
			{Name: "config", ID: 4, Type: *types.String},
			{Name: "report_id", ID: 5, Type: *types.Int},
			{Name: "violation_start", ID: 6, Type: *types.TimestampTZ, Nullable: true},
			{Name: "violating_ranges", ID: 7, Type: *types.Int},
		},
		NextColumnID: 8,
		Families: []ColumnFamilyDescriptor{
			{
				Name: "primary",
				ID:   0,
				ColumnNames: []string{
					"zone_id",
					"subzone_id",
					"type",
					"config",
					"report_id",
					"violation_start",
					"violating_ranges",
				},
				ColumnIDs: []ColumnID{1, 2, 3, 4, 5, 6, 7},
			},
		},
		NextFamilyID: 1,
		PrimaryIndex: IndexDescriptor{
			Name:        "primary",
			ID:          1,
			Unique:      true,
			ColumnNames: []string{"zone_id", "subzone_id", "type", "config"},
			ColumnDirections: []IndexDescriptor_Direction{
				IndexDescriptor_ASC, IndexDescriptor_ASC, IndexDescriptor_ASC, IndexDescriptor_ASC,
			},
			ColumnIDs: []ColumnID{1, 2, 3, 4},
			Version:   SecondaryIndexFamilyFormatVersion,
		},
		NextIndexID:    2,
		Privileges:     NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.ReplicationConstraintStatsTableID]),
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}

	// TODO(andrei): In 20.1 we should add a foreign key reference to the
	// reports_meta table. Until then, it would cost us having to create an index
	// on report_id.
	ReplicationCriticalLocalitiesTable = TableDescriptor{
		Name:                    "replication_critical_localities",
		ID:                      keys.ReplicationCriticalLocalitiesTableID,
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "zone_id", ID: 1, Type: *types.Int},
			{Name: "subzone_id", ID: 2, Type: *types.Int},
			{Name: "locality", ID: 3, Type: *types.String},
			{Name: "report_id", ID: 4, Type: *types.Int},
			{Name: "at_risk_ranges", ID: 5, Type: *types.Int},
		},
		NextColumnID: 6,
		Families: []ColumnFamilyDescriptor{
			{
				Name: "primary",
				ID:   0,
				ColumnNames: []string{
					"zone_id",
					"subzone_id",
					"locality",
					"report_id",
					"at_risk_ranges",
				},
				ColumnIDs: []ColumnID{1, 2, 3, 4, 5},
			},
		},
		NextFamilyID: 1,
		PrimaryIndex: IndexDescriptor{
			Name:        "primary",
			ID:          1,
			Unique:      true,
			ColumnNames: []string{"zone_id", "subzone_id", "locality"},
			ColumnDirections: []IndexDescriptor_Direction{
				IndexDescriptor_ASC, IndexDescriptor_ASC, IndexDescriptor_ASC,
			},
			ColumnIDs: []ColumnID{1, 2, 3},
			Version:   SecondaryIndexFamilyFormatVersion,
		},
		NextIndexID:    2,
		Privileges:     NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.ReplicationCriticalLocalitiesTableID]),
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}

	ReplicationStatsTableTTL = time.Minute * 10
	// TODO(andrei): In 20.1 we should add a foreign key reference to the
	// reports_meta table. Until then, it would cost us having to create an index
	// on report_id.
	ReplicationStatsTable = TableDescriptor{
		Name:                    "replication_stats",
		ID:                      keys.ReplicationStatsTableID,
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "zone_id", ID: 1, Type: *types.Int},
			{Name: "subzone_id", ID: 2, Type: *types.Int},
			{Name: "report_id", ID: 3, Type: *types.Int},
			{Name: "total_ranges", ID: 4, Type: *types.Int},
			{Name: "unavailable_ranges", ID: 5, Type: *types.Int},
			{Name: "under_replicated_ranges", ID: 6, Type: *types.Int},
			{Name: "over_replicated_ranges", ID: 7, Type: *types.Int},
		},
		NextColumnID: 8,
		Families: []ColumnFamilyDescriptor{
			{
				Name: "primary",
				ID:   0,
				ColumnNames: []string{
					"zone_id",
					"subzone_id",
					"report_id",
					"total_ranges",
					"unavailable_ranges",
					"under_replicated_ranges",
					"over_replicated_ranges",
				},
				ColumnIDs: []ColumnID{1, 2, 3, 4, 5, 6, 7},
			},
		},
		NextFamilyID: 2,
		PrimaryIndex: IndexDescriptor{
			Name:             "primary",
			ID:               1,
			Unique:           true,
			ColumnNames:      []string{"zone_id", "subzone_id"},
			ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC, IndexDescriptor_ASC},
			ColumnIDs:        []ColumnID{1, 2},
			Version:          SecondaryIndexFamilyFormatVersion,
		},
		NextIndexID:    2,
		Privileges:     NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.ReplicationStatsTableID]),
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}

	ProtectedTimestampsMetaTable = TableDescriptor{
		Name:                    "protected_ts_meta",
		ID:                      keys.ProtectedTimestampsMetaTableID,
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{
				Name:        "singleton",
				ID:          1,
				Type:        *types.Bool,
				DefaultExpr: &trueBoolString,
			},
			{Name: "version", ID: 2, Type: *types.Int},
			{Name: "num_records", ID: 3, Type: *types.Int},
			{Name: "num_spans", ID: 4, Type: *types.Int},
			{Name: "total_bytes", ID: 5, Type: *types.Int},
		},
		Checks: []*TableDescriptor_CheckConstraint{
			{
				Name:      "check_singleton",
				Expr:      "singleton",
				ColumnIDs: []ColumnID{1},
			},
		},
		NextColumnID: 6,
		Families: []ColumnFamilyDescriptor{
			{
				Name:        "primary",
				ColumnNames: []string{"singleton", "version", "num_records", "num_spans", "total_bytes"},
				ColumnIDs:   []ColumnID{1, 2, 3, 4, 5},
			},
		},
		NextFamilyID: 1,
		PrimaryIndex: IndexDescriptor{
			Name:        "primary",
			ID:          1,
			Version:     1,
			Unique:      true,
			ColumnNames: []string{"singleton"},
			ColumnIDs:   []ColumnID{1},
			ColumnDirections: []IndexDescriptor_Direction{
				IndexDescriptor_ASC,
			},
		},
		NextIndexID:    2,
		Privileges:     NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.ReplicationStatsTableID]),
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}

	ProtectedTimestampsRecordsTable = TableDescriptor{
		Name:                    "protected_ts_records",
		ID:                      keys.ProtectedTimestampsRecordsTableID,
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "id", ID: 1, Type: *types.Uuid},
			{Name: "ts", ID: 2, Type: *types.Decimal},
			{Name: "meta_type", ID: 3, Type: *types.String},
			{Name: "meta", ID: 4, Type: *types.Bytes, Nullable: true},
			{Name: "num_spans", ID: 5, Type: *types.Int},
			{Name: "spans", ID: 6, Type: *types.Bytes},
			{Name: "verified", ID: 7, Type: *types.Bool, DefaultExpr: &falseBoolString},
		},
		NextColumnID: 8,
		Families: []ColumnFamilyDescriptor{
			{
				Name:        "primary",
				ColumnNames: []string{"id", "ts", "meta_type", "meta", "num_spans", "spans", "verified"},
				ColumnIDs:   []ColumnID{1, 2, 3, 4, 5, 6, 7},
			},
		},
		NextFamilyID: 1,
		PrimaryIndex: IndexDescriptor{
			Name:        "primary",
			ID:          1,
			Version:     1,
			Unique:      true,
			ColumnNames: []string{"id"},
			ColumnIDs:   []ColumnID{1},
			ColumnDirections: []IndexDescriptor_Direction{
				IndexDescriptor_ASC,
			},
		},
		NextIndexID:    2,
		Privileges:     NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.ProtectedTimestampsRecordsTableID]),
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}

	// RoleOptionsTable is the descriptor for the role_options table.
	RoleOptionsTable = TableDescriptor{
		Name:                    "role_options",
		ID:                      keys.RoleOptionsTableID,
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "username", ID: 1, Type: *types.String},
			{Name: "option", ID: 2, Type: *types.String},
			{Name: "value", ID: 3, Type: *types.String, Nullable: true},
		},
		NextColumnID: 4,
		Families: []ColumnFamilyDescriptor{
			{
				Name:            "primary",
				ColumnNames:     []string{"username", "option", "value"},
				ColumnIDs:       []ColumnID{1, 2, 3},
				DefaultColumnID: 3,
			},
		},
		NextFamilyID: 1,
		PrimaryIndex: IndexDescriptor{
			Name:             "primary",
			ID:               1,
			Unique:           true,
			ColumnNames:      []string{"username", "option"},
			ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC, IndexDescriptor_ASC},
			ColumnIDs:        []ColumnID{1, 2},
			Version:          SecondaryIndexFamilyFormatVersion,
		},
		NextIndexID:    2,
		Privileges:     NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.RoleOptionsTableID]),
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}

	StatementBundleChunksTable = TableDescriptor{
		Name:                    "statement_bundle_chunks",
		ID:                      keys.StatementBundleChunksTableID,
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "id", ID: 1, Type: *types.Int, DefaultExpr: &uniqueRowIDString},
			{Name: "description", ID: 2, Type: *types.String, Nullable: true},
			{Name: "data", ID: 3, Type: *types.Bytes},
		},
		NextColumnID: 4,
		Families: []ColumnFamilyDescriptor{
			{
				Name:        "primary",
				ColumnNames: []string{"id", "description", "data"},
				ColumnIDs:   []ColumnID{1, 2, 3},
			},
		},
		NextFamilyID:   1,
		PrimaryIndex:   pk("id"),
		NextIndexID:    2,
		Privileges:     NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.StatementBundleChunksTableID]),
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}

	// TODO(andrei): Add a foreign key reference to the statement_diagnostics table when
	// it no longer requires us to create an index on statement_diagnostics_id.
	StatementDiagnosticsRequestsTable = TableDescriptor{
		Name:                    "statement_diagnostics_requests",
		ID:                      keys.StatementDiagnosticsRequestsTableID,
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "id", ID: 1, Type: *types.Int, DefaultExpr: &uniqueRowIDString, Nullable: false},
			{Name: "completed", ID: 2, Type: *types.Bool, Nullable: false, DefaultExpr: &falseBoolString},
			{Name: "statement_fingerprint", ID: 3, Type: *types.String, Nullable: false},
			{Name: "statement_diagnostics_id", ID: 4, Type: *types.Int, Nullable: true},
			{Name: "requested_at", ID: 5, Type: *types.TimestampTZ, Nullable: false},
		},
		NextColumnID: 6,
		Families: []ColumnFamilyDescriptor{
			{
				Name:        "primary",
				ColumnNames: []string{"id", "completed", "statement_fingerprint", "statement_diagnostics_id", "requested_at"},
				ColumnIDs:   []ColumnID{1, 2, 3, 4, 5},
			},
		},
		NextFamilyID: 1,
		PrimaryIndex: pk("id"),
		// Index for the polling query.
		Indexes: []IndexDescriptor{
			{
				Name:             "completed_idx",
				ID:               2,
				Unique:           false,
				ColumnNames:      []string{"completed", "id"},
				StoreColumnNames: []string{"statement_fingerprint"},
				ColumnIDs:        []ColumnID{2, 1},
				ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC, IndexDescriptor_ASC},
				StoreColumnIDs:   []ColumnID{3},
				Version:          SecondaryIndexFamilyFormatVersion,
			},
		},
		NextIndexID: 3,
		Privileges: NewCustomSuperuserPrivilegeDescriptor(
			SystemAllowedPrivileges[keys.StatementDiagnosticsRequestsTableID]),
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}

	StatementDiagnosticsTable = TableDescriptor{
		Name:                    "statement_diagnostics",
		ID:                      keys.StatementDiagnosticsTableID,
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "id", ID: 1, Type: *types.Int, DefaultExpr: &uniqueRowIDString, Nullable: false},
			{Name: "statement_fingerprint", ID: 2, Type: *types.String, Nullable: false},
			{Name: "statement", ID: 3, Type: *types.String, Nullable: false},
			{Name: "collected_at", ID: 4, Type: *types.TimestampTZ, Nullable: false},
			{Name: "trace", ID: 5, Type: *types.Jsonb, Nullable: true},
			{Name: "bundle_chunks", ID: 6, Type: *types.IntArray, Nullable: true},
			{Name: "error", ID: 7, Type: *types.String, Nullable: true},
		},
		NextColumnID: 8,
		Families: []ColumnFamilyDescriptor{
			{
				Name: "primary",
				ColumnNames: []string{"id", "statement_fingerprint", "statement",
					"collected_at", "trace", "bundle_chunks", "error"},
				ColumnIDs: []ColumnID{1, 2, 3, 4, 5, 6, 7},
			},
		},
		NextFamilyID: 1,
		PrimaryIndex: pk("id"),
		NextIndexID:  2,
		Privileges: NewCustomSuperuserPrivilegeDescriptor(
			SystemAllowedPrivileges[keys.StatementDiagnosticsTableID]),
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}

	KWDBTsTableTable = TableDescriptor{
		Name:                    "kwdb_ts_table",
		ID:                      keys.KWDBTsTableID,
		Privileges:              NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.KWDBTsTableID]),
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "instance_id", ID: 1, Type: *types.Int4},
			{Name: "db_name", ID: 2, Type: *types.String},
			{Name: "instance_name", ID: 3, Type: *types.String},
			{Name: "template_id", ID: 4, Type: *types.Int4},
			{Name: "desc", ID: 5, Type: *types.Bytes},
		},
		NextColumnID: 6,
		Families: []ColumnFamilyDescriptor{
			{Name: "fam_all_column", ID: 0, ColumnNames: []string{"instance_id", "db_name", "instance_name", "template_id", "desc"}, ColumnIDs: []ColumnID{1, 2, 3, 4, 5}},
		},
		PrimaryIndex: pk("instance_id"),
		Indexes: []IndexDescriptor{
			{
				Name:             "unique_instance_name_idx",
				ID:               2,
				Unique:           true,
				ColumnNames:      []string{"db_name", "instance_name"},
				ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC, IndexDescriptor_ASC},
				ColumnIDs:        []ColumnID{2, 3},
				Version:          SecondaryIndexFamilyFormatVersion,
				ExtraColumnIDs:   []ColumnID{1},
			},
		},
		NextFamilyID:   1,
		NextIndexID:    3,
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}
	// 19
	DefaultHighWater         = "'0,0'"
	KWDBReplicationInfoTable = TableDescriptor{
		Name:                    "kwdb_replication_info",
		ID:                      keys.KWDBReplicationInfoID,
		Privileges:              NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.KWDBReplicationInfoID]),
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "replica_id", ID: 1, Type: *types.Int4, DefaultExpr: &uniqueRowIDString, Nullable: false},
			{Name: "replica_name", ID: 2, Type: *types.String},
			{Name: "replica_level", ID: 3, Type: *types.Int2},
			{Name: "src_cluster_id", ID: 4, Type: *types.String},
			{Name: "dest_cluster_id", ID: 5, Type: *types.String},
			{Name: "agent_type", ID: 6, Type: *types.Int4},
			{Name: "status", ID: 7, Type: *types.Int4},
			{Name: "replica_desc", ID: 8, Type: *types.Int4},
			{Name: "replica_desc_name", ID: 9, Type: *types.String},
			{Name: "replica_param", ID: 10, Type: *types.Bytes},
			{Name: "replica_high_water", ID: 11, Type: *types.String, DefaultExpr: &DefaultHighWater},
			{Name: "replica_rdbms_repl_done", ID: 12, Type: *types.Bool, Nullable: true, DefaultExpr: &trueBoolString},
		},
		NextColumnID: 13,
		Families: []ColumnFamilyDescriptor{
			// The id of the first col fam is hardcoded in keys.MakeDescMetadataKey().
			{Name: "primary", ID: 0, ColumnNames: []string{"agent_type", "replica_desc"}, ColumnIDs: []ColumnID{6, 8}},
			{Name: "fam_2_descriptor", ID: 2,
				ColumnNames: []string{"replica_id", "replica_name", "replica_level", "src_cluster_id", "dest_cluster_id", "status", "replica_desc_name", "replica_param", "replica_high_water", "replica_rdbms_repl_done"},
				ColumnIDs:   []ColumnID{1, 2, 3, 4, 5, 7, 9, 10, 11, 12}},
		},
		PrimaryIndex: IndexDescriptor{
			Name:             "primary",
			ID:               1,
			Unique:           true,
			ColumnNames:      []string{"agent_type", "replica_desc"},
			ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC, IndexDescriptor_ASC},
			ColumnIDs:        []ColumnID{6, 8},
			Version:          SecondaryIndexFamilyFormatVersion,
		},
		NextFamilyID:   3,
		NextIndexID:    2,
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}

	// BoBlackListTable is the descriptor for the bo_black_list table.
	BoBlackListTable = TableDescriptor{
		Name:                    "bo_black_list",
		ID:                      keys.KWDBBoBlackListTableID,
		Privileges:              NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.KWDBBoBlackListTableID]),
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "rowid", ID: 1, Type: *types.Int, DefaultExpr: &uniqueRowIDString, Hidden: true},
			{Name: "name", ID: 2, Type: *types.String},
			{Name: "arg_num", ID: 3, Type: *types.Int2},
			{Name: "arg_type", ID: 4, Type: *types.Int2Array},
			{Name: "position", ID: 5, Type: *types.Int2},
			{Name: "enabled", ID: 6, Type: *types.Bool},
			{Name: "arg_opt", ID: 7, Type: *types.Int2},
		},
		NextColumnID: 8,
		Families: []ColumnFamilyDescriptor{
			{Name: "primary", ID: 0, ColumnNames: []string{"rowid"}, ColumnIDs: []ColumnID{1}},
			{Name: "fam_2_id", ID: 1, ColumnNames: []string{"name", "arg_num", "arg_type", "position", "enabled", "arg_opt"}, ColumnIDs: []ColumnID{2, 3, 4, 5, 6, 7}},
		},
		NextFamilyID:   2,
		PrimaryIndex:   pk("rowid"),
		NextIndexID:    2,
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}

	// DefinedFunctionTable is user defined function table.
	// table id: 55
	DefinedFunctionTable = TableDescriptor{
		Name:                    "user_defined_function",
		ID:                      keys.DefinedFunctionTableID,
		Privileges:              NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.DefinedFunctionTableID]),
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "function_name", ID: 1, Type: *types.String},
			{Name: "argument_types", ID: 2, Type: *types.IntArray},
			{Name: "return_type", ID: 3, Type: *types.IntArray},
			{Name: "types_length", ID: 4, Type: *types.IntArray},
			{Name: "function_body", ID: 5, Type: *types.String},
			{Name: "function_type", ID: 6, Type: *types.Int},
			{Name: "language", ID: 7, Type: *types.String},
			{Name: "db_name", ID: 8, Type: *types.String},
			{Name: "creator", ID: 9, Type: *types.String},
			{Name: "create_time", ID: 10, Type: *types.Timestamp},
			{Name: "version", ID: 11, Type: *types.String},
			{Name: "comments", ID: 12, Type: *types.String},
		},
		NextColumnID: 13,
		Families: []ColumnFamilyDescriptor{
			{Name: "primary", ID: 0, ColumnNames: []string{"function_name"}, ColumnIDs: []ColumnID{1}},
			{Name: "fam_2_id", ID: 1, ColumnNames: []string{"argument_types", "return_type", "types_length", "function_body", "function_type", "language", "db_name", "creator", "create_time", "version", "comments"}, ColumnIDs: []ColumnID{2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}},
		},
		NextFamilyID:   2,
		PrimaryIndex:   pk("function_name"),
		NextIndexID:    2,
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}

	// AuditsTable is the descriptor for the audits table.
	AuditsTable = TableDescriptor{
		Name:                    "audits",
		ID:                      keys.AuditsTableID,
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "audit_name", ID: 1, Type: *types.String},
			{Name: "target_type", ID: 2, Type: *types.String},
			{Name: "target_id", ID: 3, Type: *types.Int, Nullable: true},
			{Name: "operations", ID: 4, Type: *types.StringArray},
			{Name: "operators", ID: 5, Type: *types.StringArray},
			{Name: "condition", ID: 6, Type: *types.Int, Nullable: true},
			{Name: "whenever", ID: 7, Type: *types.String},
			{Name: "action", ID: 8, Type: *types.Int, Nullable: true},
			{Name: "level", ID: 9, Type: *types.Int, Nullable: true},
			{Name: "enable", ID: 10, Type: *types.Bool},
		},
		NextColumnID: 11,
		Families: []ColumnFamilyDescriptor{
			{Name: "fam_0_audit_name", ID: 0, ColumnNames: []string{"audit_name"}, ColumnIDs: []ColumnID{1}},
			{Name: "fam_2_target_type", ID: 2, ColumnNames: []string{"target_type"}, ColumnIDs: []ColumnID{2}, DefaultColumnID: 2},
			{Name: "fam_3_target_id", ID: 3, ColumnNames: []string{"target_id"}, ColumnIDs: []ColumnID{3}, DefaultColumnID: 3},
			{Name: "fam_4_operations", ID: 4, ColumnNames: []string{"operations"}, ColumnIDs: []ColumnID{4}, DefaultColumnID: 4},
			{Name: "fam_5_operators", ID: 5, ColumnNames: []string{"operators"}, ColumnIDs: []ColumnID{5}, DefaultColumnID: 5},
			{Name: "fam_6_condition", ID: 6, ColumnNames: []string{"condition"}, ColumnIDs: []ColumnID{6}, DefaultColumnID: 6},
			{Name: "fam_7_whenever", ID: 7, ColumnNames: []string{"whenever"}, ColumnIDs: []ColumnID{7}, DefaultColumnID: 7},
			{Name: "fam_8_action", ID: 8, ColumnNames: []string{"action"}, ColumnIDs: []ColumnID{8}, DefaultColumnID: 8},
			{Name: "fam_9_level", ID: 9, ColumnNames: []string{"level"}, ColumnIDs: []ColumnID{9}, DefaultColumnID: 9},
			{Name: "fam_10_enable", ID: 10, ColumnNames: []string{"enable"}, ColumnIDs: []ColumnID{10}, DefaultColumnID: 10},
		},
		NextFamilyID:   11,
		PrimaryIndex:   pk("audit_name"),
		NextIndexID:    2,
		Privileges:     NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.AuditsTableID]),
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}

	KWDBHashRoutingTable = TableDescriptor{
		Name:                    "kwdb_hash_routing",
		ID:                      keys.KWDBHashRoutingTableID,
		Privileges:              NewCustomSuperuserPrivilegeDescriptor(SystemAllowedPrivileges[keys.KWDBHashRoutingTableID]),
		ParentID:                keys.SystemDatabaseID,
		UnexposedParentSchemaID: keys.PublicSchemaID,
		Version:                 1,
		Columns: []ColumnDescriptor{
			{Name: "entity_range_group_id", ID: 1, Type: *types.Int},
			{Name: "table_id", ID: 2, Type: *types.Int},
			{Name: "entity_range_group", ID: 3, Type: *types.Bytes},
			{Name: "ts_partition_size", ID: 4, Type: *types.Int},
		},
		NextColumnID: 5,
		Families: []ColumnFamilyDescriptor{
			{Name: "primary", ID: 0,
				ColumnNames: []string{"entity_range_group_id", "table_id", "entity_range_group", "ts_partition_size"},
				ColumnIDs:   []ColumnID{1, 2, 3, 4}},
		},
		NextFamilyID: 1,
		PrimaryIndex: IndexDescriptor{
			Name:             "primary",
			ID:               1,
			Unique:           true,
			ColumnNames:      []string{"entity_range_group_id"},
			ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC},
			ColumnIDs:        singleID1,
			Version:          SecondaryIndexFamilyFormatVersion,
		},
		Indexes: []IndexDescriptor{
			{
				Name:             "kwdb_hash_routing_table_id_idx",
				ID:               2,
				Unique:           false,
				ColumnNames:      []string{"table_id"},
				ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC},
				ColumnIDs:        []ColumnID{2},
				ExtraColumnIDs:   []ColumnID{1},
				Version:          SecondaryIndexFamilyFormatVersion,
			},
		},
		NextIndexID:    3,
		FormatVersion:  InterleavedFormatVersion,
		NextMutationID: 1,
	}
)

// Create a kv pair for the zone config for the given key and config value.
func createZoneConfigKV(keyID int, zoneConfig *zonepb.ZoneConfig) roachpb.KeyValue {
	value := roachpb.Value{}
	if err := value.SetProto(zoneConfig); err != nil {
		panic(fmt.Sprintf("could not marshal ZoneConfig for ID: %d: %s", keyID, err))
	}
	return roachpb.KeyValue{
		Key:   keys.ZoneKey(uint32(keyID)),
		Value: value,
	}
}

// addSystemDescriptorsToSchema populates the supplied MetadataSchema
// with the system database and table descriptors. The descriptors for
// these objects exist statically in this file, but a MetadataSchema
// can be used to persist these descriptors to the kwbase store.
func addSystemDescriptorsToSchema(target *MetadataSchema) {
	// Add system database.
	target.AddDescriptor(keys.RootNamespaceID, &SystemDB)

	// Add system config tables.
	target.AddDescriptor(keys.SystemDatabaseID, &DeprecatedNamespaceTable)
	target.AddDescriptor(keys.SystemDatabaseID, &NamespaceTable)
	target.AddDescriptor(keys.SystemDatabaseID, &DescriptorTable)
	target.AddDescriptor(keys.SystemDatabaseID, &UsersTable)
	target.AddDescriptor(keys.SystemDatabaseID, &ZonesTable)
	target.AddDescriptor(keys.SystemDatabaseID, &SettingsTable)

	// Add all the other system tables.
	target.AddDescriptor(keys.SystemDatabaseID, &LeaseTable)
	target.AddDescriptor(keys.SystemDatabaseID, &EventLogTable)
	target.AddDescriptor(keys.SystemDatabaseID, &RangeEventTable)
	target.AddDescriptor(keys.SystemDatabaseID, &UITable)
	target.AddDescriptor(keys.SystemDatabaseID, &JobsTable)
	target.AddDescriptor(keys.SystemDatabaseID, &WebSessionsTable)
	target.AddDescriptor(keys.SystemDatabaseID, &RoleOptionsTable)

	// Tables introduced in 2.0, added here for 2.1.
	target.AddDescriptor(keys.SystemDatabaseID, &TableStatisticsTable)
	target.AddDescriptor(keys.SystemDatabaseID, &LocationsTable)
	target.AddDescriptor(keys.SystemDatabaseID, &RoleMembersTable)

	// The CommentsTable has been introduced in 2.2. It was added here since it
	// was introduced, but it's also created as a migration for older clusters.
	target.AddDescriptor(keys.SystemDatabaseID, &CommentsTable)
	target.AddDescriptor(keys.SystemDatabaseID, &ReportsMetaTable)
	target.AddDescriptor(keys.SystemDatabaseID, &ReplicationConstraintStatsTable)
	target.AddDescriptor(keys.SystemDatabaseID, &ReplicationStatsTable)
	target.AddDescriptor(keys.SystemDatabaseID, &ReplicationCriticalLocalitiesTable)
	target.AddDescriptor(keys.SystemDatabaseID, &ProtectedTimestampsMetaTable)
	target.AddDescriptor(keys.SystemDatabaseID, &ProtectedTimestampsRecordsTable)

	// Tables introduced in 20.1.
	target.AddDescriptor(keys.SystemDatabaseID, &StatementBundleChunksTable)
	target.AddDescriptor(keys.SystemDatabaseID, &StatementDiagnosticsRequestsTable)
	target.AddDescriptor(keys.SystemDatabaseID, &StatementDiagnosticsTable)

	// KWDB tables
	target.AddDescriptor(keys.SystemDatabaseID, &KWDBReplicationInfoTable)
	target.AddDescriptor(keys.SystemDatabaseID, &AuditsTable)
	target.AddDescriptor(keys.SystemDatabaseID, &BoBlackListTable)
	target.AddDescriptor(keys.SystemDatabaseID, &DefinedFunctionTable)
	target.AddDescriptor(keys.SystemDatabaseID, &KWDBTsTableTable)
	target.AddDescriptor(keys.SystemDatabaseID, &ScheduledJobsTable)
	target.AddDescriptor(keys.SystemDatabaseID, &KWDBHashRoutingTable)
}

// addSystemDatabaseToSchema populates the supplied MetadataSchema with the
// System database, its tables and zone configurations.
func addSystemDatabaseToSchema(
	target *MetadataSchema,
	defaultZoneConfig *zonepb.ZoneConfig,
	defaultSystemZoneConfig *zonepb.ZoneConfig,
) {
	addSystemDescriptorsToSchema(target)

	target.AddSplitIDs(keys.PseudoTableIDs...)

	// Adding a new system table? It should be added here to the metadata schema,
	// and also created as a migration for older cluster. The includedInBootstrap
	// field should be set on the migration.

	target.otherKV = append(target.otherKV, createZoneConfigKV(keys.RootNamespaceID, defaultZoneConfig))

	systemZoneConf := defaultSystemZoneConfig
	metaRangeZoneConf := protoutil.Clone(defaultSystemZoneConfig).(*zonepb.ZoneConfig)
	livenessZoneConf := protoutil.Clone(defaultSystemZoneConfig).(*zonepb.ZoneConfig)

	// .meta zone config entry with a shorter GC time.
	metaRangeZoneConf.GC.TTLSeconds = 60 * 60 // 1h
	target.otherKV = append(target.otherKV, createZoneConfigKV(keys.MetaRangesID, metaRangeZoneConf))

	// Some reporting tables have shorter GC times.
	replicationConstraintStatsZoneConf := &zonepb.ZoneConfig{
		GC: &zonepb.GCPolicy{TTLSeconds: int32(ReplicationConstraintStatsTableTTL.Seconds())},
	}
	replicationStatsZoneConf := &zonepb.ZoneConfig{
		GC: &zonepb.GCPolicy{TTLSeconds: int32(ReplicationStatsTableTTL.Seconds())},
	}

	// Liveness zone config entry with a shorter GC time.
	livenessZoneConf.GC.TTLSeconds = 10 * 60 // 10m
	target.otherKV = append(target.otherKV, createZoneConfigKV(keys.LivenessRangesID, livenessZoneConf))
	target.otherKV = append(target.otherKV, createZoneConfigKV(keys.SystemRangesID, systemZoneConf))
	target.otherKV = append(target.otherKV, createZoneConfigKV(keys.SystemDatabaseID, systemZoneConf))
	target.otherKV = append(target.otherKV,
		createZoneConfigKV(keys.ReplicationConstraintStatsTableID, replicationConstraintStatsZoneConf))
	target.otherKV = append(target.otherKV,
		createZoneConfigKV(keys.ReplicationStatsTableID, replicationStatsZoneConf))
}

// IsSystemConfigID returns whether this ID is for a system config object.
func IsSystemConfigID(id ID) bool {
	return id > 0 && id <= keys.MaxSystemConfigDescID
}

// IsReservedID returns whether this ID is for any system object.
func IsReservedID(id ID) bool {
	return id > 0 && id <= keys.MaxReservedDescID
}

// newCommentPrivilegeDescriptor returns a privilege descriptor for comment table
func newCommentPrivilegeDescriptor(priv privilege.List) *PrivilegeDescriptor {
	selectPriv := privilege.List{privilege.SELECT}
	return &PrivilegeDescriptor{
		Users: []UserPrivileges{
			{
				User:       AdminRole,
				Privileges: priv.ToBitField(),
			},
			{
				User:       PublicRole,
				Privileges: selectPriv.ToBitField(),
			},
			{
				User:       security.RootUser,
				Privileges: priv.ToBitField(),
			},
		},
	}
}
